"""
日志格式化器。

提供各种日志格式化器，用于自定义日志输出的格式和样式，
支持彩色输出、JSON格式、结构化格式等。
"""

import json
import logging
import traceback
from datetime import datetime
from typing import Any, Dict, Optional, Union


class ColoredFormatter(logging.Formatter):
    """
    为控制台输出添加颜色的格式化器。

    根据日志级别为输出添加不同的颜色。
    """

    # ANSI 颜色代码
    COLORS = {
        "DEBUG": "\033[94m",  # 蓝色
        "INFO": "\033[92m",  # 绿色
        "WARNING": "\033[93m",  # 黄色
        "ERROR": "\033[91m",  # 红色
        "CRITICAL": "\033[95m",  # 紫红色
        "RESET": "\033[0m",  # 重置
    }

    def __init__(self, fmt: str = None, datefmt: str = None, style: str = "%"):
        """
        初始化彩色格式化器。

        Args:
            fmt: 格式字符串
            datefmt: 日期格式字符串
            style: 格式化样式 ('%', '{', '$')
        """
        if fmt is None:
            fmt = "%(asctime)s - %(levelname)5s - %(name)s - %(message)s"
        super().__init__(fmt, datefmt, style)

    def format(self, record: logging.LogRecord) -> str:
        """
        格式化日志记录，添加颜色。

        Args:
            record: 日志记录对象

        Returns:
            str: 格式化后的日志字符串
        """
        # 保存原始的级别名称
        levelname = record.levelname

        # 添加颜色代码
        if levelname in self.COLORS:
            record.levelname = (
                f"{self.COLORS[levelname]}{levelname}{self.COLORS['RESET']}"
            )

        # 格式化记录
        result = super().format(record)

        # 恢复原始级别名称
        record.levelname = levelname

        return result


class JsonFormatter(logging.Formatter):
    """
    将日志格式化为JSON字符串。

    便于机器解析和结构化存储。
    """

    def __init__(self, additional_fields: Dict[str, Any] = None):
        """
        初始化JSON格式化器。

        Args:
            additional_fields: 添加到每条日志记录的额外字段
        """
        super().__init__()
        self.additional_fields = additional_fields or {}

    def format(self, record: logging.LogRecord) -> str:
        """
        格式化日志记录为JSON字符串。

        Args:
            record: 日志记录对象

        Returns:
            str: JSON格式的日志字符串
        """
        # 创建基础日志结构
        log_data = {
            "timestamp": datetime.fromtimestamp(record.created).isoformat(),
            "level": record.levelname,
            "name": record.name,
            "message": record.getMessage(),
        }

        # 添加源代码位置
        log_data.update(
            {
                "file": record.pathname,
                "line": record.lineno,
                "function": record.funcName,
            }
        )

        # 添加异常信息
        if record.exc_info:
            log_data["exception"] = {
                "type": record.exc_info[0].__name__,
                "message": str(record.exc_info[1]),
                "traceback": traceback.format_exception(*record.exc_info),
            }

        # 添加额外字段
        log_data.update(self.additional_fields)

        # 如果record有额外属性
        if hasattr(record, "props"):
            log_data.update(record.props)

        return json.dumps(log_data)


class StructuredFormatter(logging.Formatter):
    """
    结构化日志格式化器，保留标准格式但支持添加结构化数据。

    允许通过日志记录中的props属性添加结构化数据。
    """

    def __init__(self, fmt: str = None, datefmt: str = None, style: str = "%"):
        """
        初始化结构化格式化器。

        Args:
            fmt: 格式字符串
            datefmt: 日期格式字符串
            style: 格式化样式 ('%', '{', '$')
        """
        if fmt is None:
            fmt = "%(asctime)s - %(levelname)5s - %(name)s - %(message)s"
        super().__init__(fmt, datefmt, style)

    def format(self, record: logging.LogRecord) -> str:
        """
        格式化日志记录，添加结构化数据。

        Args:
            record: 日志记录对象

        Returns:
            str: 格式化后的日志字符串
        """
        # 首先使用标准格式化
        result = super().format(record)

        # 如果有附加的结构化数据，添加到输出中
        if hasattr(record, "props") and record.props:
            # 缩进JSON以使其对齐
            prop_json = json.dumps(record.props, indent=2)
            indented_json = "\n".join("    " + line for line in prop_json.split("\n"))
            result = f"{result}\n{indented_json}"

        return result


def create_formatter(formatter_type: str, **kwargs) -> logging.Formatter:
    """
    创建指定类型的格式化器。

    Args:
        formatter_type: 格式化器类型，可选值：'colored', 'json', 'structured'
        **kwargs: 传递给特定格式化器的额外参数

    Returns:
        logging.Formatter: 创建的格式化器

    Raises:
        ValueError: 如果指定了无效的格式化器类型
    """
    if formatter_type == "colored":
        return ColoredFormatter(**kwargs)
    elif formatter_type == "json":
        return JsonFormatter(**kwargs)
    elif formatter_type == "structured":
        return StructuredFormatter(**kwargs)
    elif formatter_type == "standard":
        return logging.Formatter(**kwargs)
    else:
        raise ValueError(f"不支持的格式化器类型: {formatter_type}")
